package sk.hackcraft.util.agent_simulation.messaging;

import java.util.Stack;

public abstract class Message implements Comparable<Message>
{
	private final MessageCode messageCode;
	private MessageType messageType;
	
	private MessageProcessor addressee;
	
	private double deliveryTime;
	
	private final Stack<MessageProcessor> sendersBuffer;
	
	public Message(double deliveryTime, MessageCode code, MessageProcessor addressee)
	{
		this.sendersBuffer = new Stack<MessageProcessor>();
		this.deliveryTime = deliveryTime;
		this.addressee = addressee;
		this.messageCode = code;
	}
	
	public Message(double deliveryTime, MessageCode code)
	{
		this(deliveryTime, code, null);
	}
	
	public Message(MessageCode code)
	{
		this(0, code, null);
	}
	
	public Message(MessageCode code, MessageProcessor addressee)
	{
		this(0, code, addressee);
	}
	
	public Message(Message message)
	{
		this.messageCode = message.messageCode;
		this.messageType = message.messageType;
		
		this.addressee = message.addressee;
	
		this.deliveryTime = message.deliveryTime;
		
		this.sendersBuffer = (Stack<MessageProcessor>) message.sendersBuffer.clone();
	}
	
	public double getDeliveryTime()
	{
		return this.deliveryTime;
	}

	public void setDeliveryTime(double deliveryTime)
	{
		this.deliveryTime = deliveryTime;
	}

	public MessageProcessor getAddressee()
	{
		return addressee;
	}
	
	public boolean hasAddressee()
	{
		return addressee != null;
	}
	
	public void setAddressee(MessageProcessor addressee)
	{
		this.addressee = addressee;
	}
	
	public void addToSendersBuffer(MessageProcessor sender)
	{
		this.sendersBuffer.push(sender);
	}
	
	public boolean canBeReturned()
	{
		return !sendersBuffer.empty();
	}
	
	public void setLastSenderAsAddressee()
	{
		this.addressee = this.sendersBuffer.pop();
	}

	public MessageCode getMessageCode()
	{
		return messageCode;
	}

	public MessageType getMessageType()
	{
		return messageType;
	}

	public void setMessageType(MessageType messageType)
	{
		this.messageType = messageType;
	}
	
	@Override
	public int compareTo(Message message)
	{
		if(this.getDeliveryTime() > message.getDeliveryTime())
		{
			return 1;
		}
		else if(this.getDeliveryTime() < message.getDeliveryTime())
		{
			return -1;
		}
		else
		{
			return 0;
		}
	}
	
	public abstract Message createCopy();
}
